package net.funtip.ormgenerator.model;

import net.funtip.ormgenerator.generator.TypeMapper;
import net.funtip.ormgenerator.util.Tools;

public class Attribute {

	private String name;
	private String type;
	private String columnName;
	private String columnType;
	private boolean mandatory;
	private String defaultValue;
	private Entity entity;
	private boolean identifier;
	private String calculatedValue;
	private boolean isTransient;
	private boolean associated;
	private boolean idGenerated;
	private String generatorType;
	private String sequenceName;
	private boolean includedInEquals;
	private boolean unique;
	private Association association;

	public Attribute(String type, String name, Entity owner) {
		this.name = name;
		this.type = type;
		this.entity = owner;
		this.includedInEquals = true;
		this.unique = false;
		entity.addAttribute(this);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getShortTypeName() {
		return Tools.getTypeNameWithoutPackage(getType());
	}

	public String getColumnName() {
		if (columnName == null || columnName.isEmpty()) {
			columnName = entity.getColumnPrefix()+generateColumnName(name);
		}
		return columnName;
	}

	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}

	public String getColumnType() {
		if (columnType == null || columnType.isEmpty()) {
			TypeMapper typeMapper = getTypeMapper();
			if (typeMapper != null) {
				columnType = typeMapper.getMappedType(type);
			}
			if (columnType == null) {
				// FIXME
				columnType = "TYPE:UNKNOWN";
			}
		}
		return columnType;
	}

	public void setColumnType(String columnType) {
		this.columnType = columnType;
	}

	public boolean isMandatory() {
		return mandatory;
	}

	public void setMandatory(boolean mandatory) {
		this.mandatory = mandatory;
	}

	public String getDefaultValue() {
		return defaultValue;
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public Entity getEntity() {
		return entity;
	}

	public String getCalculatedValue() {
		return calculatedValue;
	}

	public void setCalculatedValue(String calculatedValue) {
		this.calculatedValue = calculatedValue;
	}

	public String getNameCapitalized() {
		if (name == null || name.length() == 0) return name;
		return name.substring(0, 1).toUpperCase() + name.substring(1);
	}

	@Override
	public String toString() {
		return "Attribute [name=" + name + ", type=" + type + "]";
	}

	public String getGetterName() {
		if ("boolean".equals(type) || "Boolean".equals(type) || "java.lang.Boolean".equals(type)) {
			return "is"+getNameCapitalized();
		} else {
			return "get"+getNameCapitalized();
		}
	}

	public String getSetterName() {
		return "set"+getNameCapitalized();
	}

	public boolean isTransient() {
		return isTransient || (getCalculatedValue() != null && !getCalculatedValue().isEmpty());
	}

	public void setTransient(boolean isTransient) {
		this.isTransient = isTransient;
	}

	protected String generateColumnName(String s) {
		String name = "";
		boolean lastLetterLowerCase = false;
		for (int index=0; index < s.length(); index++) {
			String letter = s.substring(index, index+1);
			if (letter.equals(letter.toUpperCase())) {
				if (index > 0 && lastLetterLowerCase) {
					name += "_";
				}
			}
			name += letter.toUpperCase();
			lastLetterLowerCase = letter.equals(letter.toLowerCase());
		}
		return name;
	}

	public Model getModel() {
		return this.entity.getModel();
	}
	
	public TypeMapper getTypeMapper() {
		return getModel().getTypeMapper();
	}

	public boolean isAssociated() {
		return associated;
	}

	public void setAssociated(boolean associated) {
		this.associated = associated;
	}

	public boolean isIdentifier() {
		return identifier;
	}

	public void setIdentifier(boolean identifier) {
		this.identifier = identifier;
	}

	public String getGeneratorType() {
		return generatorType;
	}

	public void setGeneratorType(String generatorType) {
		this.generatorType = generatorType;
	}

	public String getSequenceName() {
		return sequenceName;
	}

	public void setSequenceName(String sequenceName) {
		this.sequenceName = sequenceName;
	}

	public boolean isIdGenerated() {
		return idGenerated;
	}

	public void setIdGenerated(boolean idGenerated) {
		this.idGenerated = idGenerated;
	}

	public boolean isIncludedInEquals() {
		return includedInEquals;
	}


	public void setIncludedInEquals(boolean includedInEquals) {
		this.includedInEquals = includedInEquals;
	}

	public boolean isUnique() {
		return unique;
	}

	public void setUnique(boolean unique) {
		this.unique = unique;
	}

	public boolean isScalarType() {
		if ("int".equals(type) ||
				"long".equals(type) ||
				"float".equals(type) ||
				"double".equals(type) ||
				"char".equals(type) ||
				"boolean".equals(type) ||
				"byte".equals(type)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isNumericType() {
		if ("int".equals(type) ||
				"long".equals(type) ||
				"float".equals(type) ||
				"double".equals(type) ||
				"char".equals(type) ||
				"byte".equals(type)) {
			return true;
		} else {
			return false;
		}
	}

	public Association getAssociation() {
		return association;
	}

	public void setAssociation(Association association) {
		this.association = association;
	}

}
